/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#ifndef SEQUENCEGENERATOR_HPP
#define SEQUENCEGENERATOR_HPP

#include "cpputils/CppUtils.hpp"

namespace cpputils {
	namespace utils {

		/**
		 * A simple sequence generator are used for generate integral identifiers.
		 *
		 * @par Introduction:
		 * This implementation able to:
		 * @li Create the simple unbounded generator (bounded only by base template data type)
		 * @li Create the bounded by min/max sequence generator
		 *
		 * Implementation also provide operator ++ (postfix and prefix) overloading
		 * and all public methods is thread-safe.
		 *
		 * @par Usage:
		 * @code
		 * // Create sequence generator for unsigned long (it's default data type)
		 * SequenceGenerator<> oDefGenerator;
		 *
		 * oDefGenerator.next(); // Get the next value of sequence
		 * oDefGenerator++; // Overloaded operator is supports too
		 * oDefGenerator.current(); // Get the current value of sequence
		 *
		 * // Create bounded sequence generator for int. Min value for generator is 1, Max = 3;
		 * SequenceGenerator<int> oBoundedIntGenerator(1,3);
		 * @endcode
		 */
		template<typename T = unsigned long>
		class SequenceGenerator {
		public:
			/**
			 * Default constructor for unbounded initialization.
			 * A current value is 0.
			 */
			inline SequenceGenerator();

			/**
			 * The constructor for unbounded initialization with specified initial value.
			 */
			inline SequenceGenerator(T nInitialValue);

			/**
			 * Creation a bounded sequence generator for specified min/max values
			 * The current value is nMinValue
			 */
			inline SequenceGenerator(T nMinValue, T nMaxValue);

			/**
			 * Creation a bounded sequence generator for specified min/max and initial values
			 * The current value is nInitialValue.
			 * @note If nInitialValue is lesser than nMinValue or greater than nMaxValue,
			 * then the constructor will throw std::exception
			 */
			inline SequenceGenerator(T nInitialValue, T nMinValue, T nMaxValue);

			inline ~SequenceGenerator();
			/**
			 * Return the next value
			 */
			inline T next(T nStep = 1);

			/**
			 * Return the current value
			 */
			inline T current();

			inline T getCurrentValue();
			inline void setCurrentValue ( T nValue );

			inline T getMinValue();
			inline void setMinValue ( T nValue );

			inline T getMaxValue();
			inline void setMaxValue ( T nValue );

			inline T operator++();	  // prefix operator
			inline T operator++(int); // postfix operator

			inline T operator--();	  // prefix operator
			inline T operator--(int); // postfix operator

			inline bool isBounded();
			inline void setBounded(bool);
		private:
			T m_nMinValue, m_nMaxValue;
			T m_nValue;
			bool m_bIsBounded;
			boost::recursive_mutex m_mxValue;
		};

		#include "SequenceGenerator.inl"

	}
}

#endif // SEQUENCEGENERATOR_HPP
